package ar.com.algotres.tpdos.modelo.naves;

import java.util.List;

import ar.com.algotres.tpdos.modelo.fisica.BloqueNave;
import ar.com.algotres.tpdos.modelo.fisica.CoordenadasDePosicioInvalidaException;
import ar.com.algotres.tpdos.modelo.fisica.Posicion;
import ar.com.algotres.tpdos.modelo.fisica.RepresentacionFisica;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionAbajo;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionArriba;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDerecha;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDiagonalAbajoDerecha;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDiagonalAbajoIzquierda;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDiagonalArribaDerecha;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDiagonalArribaIzquierda;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionIzquierda;
import ar.com.algotres.tpdos.modelo.fisica.disposiciones.Orientacion;
import ar.com.algotres.tpdos.modelo.fisica.movimiento.Movimiento;
import ar.com.algotres.tpdos.modelo.tablero.ContenidoCasillero;

public abstract class Nave implements ContenidoCasillero {

	protected Boolean hundido = false;
	private Movimiento movimiento;

	private RepresentacionFisica representacionFisica;

	public Nave(Posicion casilleroInicial, Orientacion orientacion, int bloques)
			throws CoordenadasDePosicioInvalidaException {
		if (casilleroInicial != null && orientacion != null) {
			representacionFisica = new RepresentacionFisica(orientacion,
					casilleroInicial, bloques);
			movimiento = Movimiento.crearMovimientoCon(orientacion.direccion());
		}
	}

	private void avanzar() throws CoordenadasDePosicioInvalidaException {
		this.moverCon(movimiento);
	}

	@Override
	public boolean equals(Object object) {
		Boolean equals;
		if (object == null) {
			equals = false;
		} else {
			Nave other = (Nave) object;
			equals = this.getClass().equals(other.getClass());
		}
		return equals;
	}

	public Boolean estasAveriada() {
		return representacionFisica.estasAveriada();
	}

	public boolean estasHundida() {
		return representacionFisica.destruidaPorCompleto();
	}

	public void explosionEn(Posicion posicion) {
		representacionFisica.explosionEn(posicion);
	}

	public List<BloqueNave> getBloques() {
		return representacionFisica.getBloques();
	}

	public boolean hayBloqueEnPosicion(Posicion posicion) {
		return representacionFisica.hayBloqueEn(posicion);
	}

	public void invertir() throws CoordenadasDePosicioInvalidaException {
		representacionFisica.invertir();
		movimiento.invertir();
	}

	public void moverAbajo() throws CoordenadasDePosicioInvalidaException {
		this.moverCon(Movimiento.crearMovimientoCon(new DireccionAbajo()));
	}

	public void moverArriba() throws CoordenadasDePosicioInvalidaException {
		this.moverCon(Movimiento.crearMovimientoCon(new DireccionArriba()));
	}

	private void moverCon(Movimiento movimiento)
			throws CoordenadasDePosicioInvalidaException {

		for (int i = 0; i < this.getBloques().size(); i++) {
			BloqueNave bloque = this.getBloques().get(0);
			Posicion posicion = movimiento.damePosicionSiguienteA(bloque
					.getPosicion());
			representacionFisica.modificarPosicionBloque(bloque, posicion);
		}
	}

	public void moverDerecha() throws CoordenadasDePosicioInvalidaException {
		this.moverCon(Movimiento.crearMovimientoCon(new DireccionDerecha()));
	}

	public void moverDiagonalDerechaAbajo()
			throws CoordenadasDePosicioInvalidaException {
		this.moverCon(Movimiento
				.crearMovimientoCon(new DireccionDiagonalAbajoDerecha()));
	}

	public void moverDiagonalDerechaArriba()
			throws CoordenadasDePosicioInvalidaException {
		this.moverCon(Movimiento
				.crearMovimientoCon(new DireccionDiagonalArribaDerecha()));
	}

	public void moverDiagonalIzquierdaAbajo()
			throws CoordenadasDePosicioInvalidaException {
		this.moverCon(Movimiento
				.crearMovimientoCon(new DireccionDiagonalAbajoIzquierda()));
	}

	public void moverDiagonalIzquierdaArriba()
			throws CoordenadasDePosicioInvalidaException {
		this.moverCon(Movimiento
				.crearMovimientoCon(new DireccionDiagonalArribaIzquierda()));
	}

	public void moverIzquierda() throws CoordenadasDePosicioInvalidaException {
		this.moverCon(Movimiento.crearMovimientoCon(new DireccionIzquierda()));
	}

	@Override
	public String toString() {
		return representacionFisica.toString();
	}

	public void vivir() throws CoordenadasDePosicioInvalidaException {
		if (!this.estasHundida())
			this.avanzar();
	}
}
